package com.dc.docs._888_面试.concurrent._4_lock;

import com.google.common.collect.Maps;

import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Description: 自定义读写锁
 * @author: gdc
 * @date: 2021/6/16
 * @version 1.0
 */
public class ReadWriteLockDemo {

    public static void main(String[] args){
        MyCache myCache = new MyCache();
        for (int i = 0; i < 5; i++) {
            final int tempInt = i;
            new Thread(() -> myCache.put(String.valueOf(tempInt), tempInt), "A_" + i).start();
        }

        for (int i = 0; i < 5; i++) {
            final int tempInt = i;
            new Thread(() -> myCache.get(String.valueOf(tempInt)), "B_" + i).start();
        }
    }
}

class MyCache{
    private volatile Map<String, Object> map = Maps.newHashMap();
    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    /**
     * 写入数据（原子+独占，整个过程必须是一个完整的统一体，中间不许被分割，被打断）
     */
    public void put(String key, Object value) {
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "，正在写入, key: " + key + ", value: " + value);
            TimeUnit.SECONDS.sleep(1);

            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写入完成, key:" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    /**
     * 获取数据（读取数据时，同时获取）
     */
    public void get(String key) {
        rwLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + ", 正在读取, key：" + key);
            TimeUnit.SECONDS.sleep(1);

            Object result = map.get(key);
            System.out.println(Thread.currentThread().getName() + ", 读取完成：" + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock();
        }
    }
}